﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IrisGenerator.Common.Core;
using IrisGenerator.Common.Core.Rules;
using IrisGenerator.Framework.RuleEngine;
using IrisGenerator.Framework.Messaging;
using IrisGenerator.Framework.Events;

namespace IrisGenerator.Common.Modules.Rules
{
    public class ModuleRule:RuleBase<Module>,IDbBindableObjectRules
    {
        public ModuleRule(Module obj) : base(obj) 
        {
            this.LinkedObject.Deleting+=new EventHandler<BaseEventArgs<Module>>(LinkedObject_Deleting);
        }

        #region Properties' Rules

        private bool ModIdIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            if (this.LinkedObject.ModId== null || this.LinkedObject.ModId.Equals(Guid.Empty))
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();
                returnValue.Add(new RuleError("Module ID", RuleErrorType.PropertyRule, "An Identifier is mandatory"));
                result = false;
            }

            return result;
        }

        private bool ModAssemblyIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            if (string.IsNullOrEmpty(this.LinkedObject.ModAssembly))
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Module Assembly", RuleErrorType.PropertyRule, "Module's Assembly is mandatory"));
                result = false;
            }

            return result;
        }

        private bool ModNameIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            if (string.IsNullOrEmpty(this.LinkedObject.ModName))
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Module Name", RuleErrorType.PropertyRule, "Module's Name is mandatory"));
                result = false;
            }

            return result;
        }

        private bool ModTypeIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            if (string.IsNullOrEmpty(this.LinkedObject.ModType))
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Module Assembly", RuleErrorType.PropertyRule, "Module's Type is mandatory"));
                result = false;
            }

            return result;
        }

        private bool ModDescriptionIsValid(ref RuleErrorCollection returnValue)
        {
            return true;
        }

        #endregion

        #region Persistancy Rules

        #region IDbBindableObjectRules

        public bool CanInsert(ref RuleErrorCollection returnValue)
        {
            bool result = true;
            result = result & !ModIdIsValid(ref returnValue);
            result = result & ModAssemblyIsValid(ref returnValue);
            result = result & ModTypeIsValid(ref returnValue);
            result = result & ModNameIsValid(ref returnValue);
            result = result & ModDescriptionIsValid(ref returnValue);

            if (PrimaryKeyExists())
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Module Object Conflict", RuleErrorType.BusinessRule, "The id already exists"));
                result = false;
            }

            return (result);
        }

        private bool PrimaryKeyExists()
        {
            var tmp = Module.Load(this.LinkedObject.ModId);
            return (tmp != null);
        }

        public bool CanUpdate(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            result = result & ModIdIsValid(ref returnValue);
            result = result & ModAssemblyIsValid(ref returnValue);
            result = result & ModTypeIsValid(ref returnValue);
            result = result & ModNameIsValid(ref returnValue);
            result = result & ModDescriptionIsValid(ref returnValue);
            
            return result;
        }
        public bool CanDelete(ref RuleErrorCollection returnValue)
        {
            return ModIdIsValid(ref returnValue);
        }

        #endregion

        #region Events Handling

        void LinkedObject_Deleting(object sender, BaseEventArgs<Module> e)
        {

            if (e.FireMessage)
            {
                Message message = new Message("Are you sure you want to delete the module " + e.Argument.ModName+ "?"
                    , "Module deletion",
                    MessageButtons.YesNo, MessageIcon.Question, MessageDefaultButton.Button2);

                MessageResults result = OnMessageSend(new MessageEventArgs<Module>(e.Argument, message));
                if (result != MessageResults.Yes)
                {
                    e.Cancel = true;
                    return;
                }
            }
        }

        /// <summary>
        /// Occures when a metatype is inserted. Adds the adequate rows to the 
        /// MetaType Equivalences.
        /// </summary>
        /// <param name="sender">The object that fires the event</param>
        /// <param name="e">The metatype base event args.</param>
        void _innerMetatype_Inserted(object sender, BaseEventArgs<Module> e)
        {
            //AddMissingEquivalences(e.Argument);
        }

        #endregion

        #endregion
    }
}
